'use strict';

const _ = require('../../libs/_');

const col = global.db.collection('todolist');

module.exports = class TodoList {
  constructor(info, creator, owner) {
    let self = this;

    self = Object.assign(self, info);

    self.createAt = new Date();
    self.creator = new ObjectId(creator._id);
    self.status = 0; // 0,create  1,complete

    if (owner) self.owner = new ObjectId(owner);

    self.children = Array.prototype.map.call(self.children, item => {
      item.status || (item.status = 0),
        item.type || (item.type = 'text');
      return item;
    });
    console.log(self);
    if (!self.title) self.temp_title = self.children[0].context;
  }

  save() {
    let self = this;

    return new Promise((resolve, reject) => {
      mongo.insertOne(col, self).then(result => {
        self._id = result.insertedId;
        self.create_at = self.createAt;
        self.createAt = new Date(self.createAt).Format('YYYY-MM-DD');
        self.process = 0;
        resolve(self);
      }).catch(reject);
    });
  }

  static detail(_id) {
    return mongo.findOneByObjectId(col, _id);
  }

  static success(_id, info) {
    return new Promise((resolve, reject) => {
      mongo.findOneByObjectId(col, _id).then(doc => {
        if (doc) {
          doc.children = Array.prototype.map.call(doc.children, item => {
            if (item.status == 0) item.status = 1, item.createAt = new Date();

            return item;
          });
          doc.status = 1;
          doc.completeAt = new Date();
          delete doc._id;
          mongo.findOneAndUpdateByObjectId(col, {
            _id: _id,
            data: doc
          }).then(result => {
            let v = doc;
            v._id = _id;
            v.process = 100;
            v.createAt = new Date(v.createAt).Format('YYYY-MM-DD');
            resolve(v);
          }).catch(reject);
        }
      }).catch(reject);
    });
  }

  static find(options) {
    var cursor = col.find(options.query, options.fileds);
    if(options.sort) cursor.sort(sort);
    return cursor;
  }

  static update(_id, info) {
    if (info.title) info.temp_title = '';

    (function() {
      let flag = 1;
      for (let i = 0; i < info.children.length; i++) {
        if (info.children[i].status == 0) flag = 0;
        if (!info.children[i].createAt) info.children[i].createAt = new Date();
        if (!info.children[i].completeAt) info.children[i].completeAt = new Date();
      }
      info.children.length && (info.children = Array.prototype.sort.call(info.children, function(a, b) {
        return a.status - b.status || (+new Date(a.createAt)) < (+new Date(b.createAt));
      }));
      // .sort(function(a, b) {
      // return a.status - b.status;
      // }));
      if (flag) info.status = 1, info.completeAt = new Date();
      else info.status = 0;
    }());

    return new Promise((resolve, reject) => {
      mongo.findOneAndUpdateByObjectId(col, {
        _id: _id,
        data: info
      }).then(result => {
        let v = result.value;
        v.createAt = new Date(v.createAt).Format('YYYY-MM-DD');
        resolve(v);
      }).catch(reject);
    });
  }

  static del(_id) {
    return new Promise((resolve, reject) => {
      mongo.deleteOneByObjectId(col, _id).then(result => {
        resolve(result);
      }).catch(reject);
    });
  }

  static notified(_id) {
    return mongo.findOneAndUpdateByObjectId(col, {
      _id: _id,
      data: { notified: 'notified' }
    });
  }

  static count(creator, info) {
    info.status && (info.status = parseInt(info.status));
    let query = Object.assign({ creator: new ObjectId(creator) }, info || {});
    return new Promise((resolve, reject) => {
      mongo.count(col,
        query
      ).then(count => {
        resolve({ count });
      }).catch(reject);
    });
  }

  static list(creator, info = {}) {
    return new Promise((resolve, reject) => {
      let query = { creator: new ObjectId(creator) };
      if (info.status > -1) query.status = parseInt(info.status);
      mongo.find(col, {
        query,
        fileds: {
          title: 1,
          temp_title: 1,
          children: 1,
          createAt: 1,
          status: 1
        },
        limit: 20,
        skip: 20 * (+info.page || 0),
        sort: {
          status: 1,
          createAt: -1,
        }
      }).then(docs => {
        let result = Array.prototype.map.call(docs, item => {
          item.createAt = new Date(item.createAt).Format('YYYY-MM-DD');
          let total = item.children.length;
          if ((!total) || (item.status == 1)) item.process = 100;
          else {
            let finished = Array.prototype.filter.call(item.children, child => { return child.status == 1; }).length;
            item.process = parseInt((finished / total) * 100);
          }
          return item;
        });
        resolve(result);
      }).catch(reject);
    });
  }
};
